package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.config.VodConstantProperties;
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.AlbumStatMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.common.util.UploadFileUtil;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.album.*;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qcloud.vod.VodUploadClient;
import com.qcloud.vod.model.VodUploadRequest;
import com.qcloud.vod.model.VodUploadResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

    @Autowired
    private TrackInfoMapper trackInfoMapper;

    @Autowired
    private VodConstantProperties vodConstantProperties;

    @Autowired
    private AlbumInfoMapper albumInfoMapper;

    @Autowired
    private VodService vodService;

    @Autowired
    private TrackStatMapper trackStatMapper;

    @Autowired
    private UserInfoFeignClient userInfoFeignClient;

    @Autowired
    private AlbumStatMapper albumStatMapper;

    /**
     * 上传声音
     *
     * @param file
     * @return
     */
    @Override
    public Map<String, Object> uploadTrack(MultipartFile file) {
        //创建上传声音客户端
        VodUploadClient client = new VodUploadClient(vodConstantProperties.getSecretId(), vodConstantProperties.getSecretKey());
        //声音上传临时目录
        String tempPath = UploadFileUtil.uploadTempPath(vodConstantProperties.getTempPath(), file);
        //构建上传请求对象
        VodUploadRequest request = new VodUploadRequest();
        //设置视频本地地址
        request.setMediaFilePath(tempPath);
        try {
            //调用上传方法
            VodUploadResponse response = client.upload(vodConstantProperties.getRegion(), request);
            Map<String, Object> map = new HashMap<>();
            map.put("mediaFileId", response.getFileId());
            map.put("mediaUrl", response.getMediaUrl());
            log.info("Upload FileId = {}", response.getFileId());
            return map;
        } catch (Exception e) {
            // 业务方进行异常处理
            log.error("Upload Err", e);
        }
        return new HashMap<>();
    }

    /**
     * 新增声音
     *
     * @param userId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveTrackInfo(Long userId, TrackInfoVo trackInfoVo) {
        //声音信息表
        TrackInfo trackInfo = new TrackInfo();
        BeanUtils.copyProperties(trackInfoVo, trackInfo);
        trackInfo.setUserId(userId);
        trackInfo.setStatus(SystemConstant.TRACK_STATUS_PASS);
        AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
        trackInfo.setOrderNum(albumInfo.getIncludeTrackCount() + 1);
        //获取流媒体信息
        TrackMediaInfoVo trackMediaInfoVo = vodService.getTrackMediaInfo(trackInfoVo.getMediaFileId());
        trackInfo.setMediaDuration(trackMediaInfoVo.getDuration());
        trackInfo.setMediaUrl(trackMediaInfoVo.getMediaUrl());
        trackInfo.setMediaSize(trackMediaInfoVo.getSize());
        trackInfo.setMediaType(trackMediaInfoVo.getType());
        this.trackInfoMapper.insert(trackInfo);

        //声音统计表
        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PLAY);
        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COLLECT);
        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PRAISE);
        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COMMENT);

        //更新专辑包含声音总数
        albumInfo.setIncludeTrackCount(trackInfo.getOrderNum());
        this.albumInfoMapper.updateById(albumInfo);

    }

    /**
     * 查询当前用户声音分页列表
     *
     * @param trackListVoPage
     * @param trackInfoQuery
     */
    @Override
    public void findAlbumTrackPage(Page<TrackListVo> trackListVoPage, TrackInfoQuery trackInfoQuery) {
        trackListVoPage = trackInfoMapper.selectAlbumTrackPage(trackListVoPage, trackInfoQuery);
    }

    /**
     * 声音统计方法
     *
     * @param id
     * @param trackStatType
     */
    private void saveTrackStat(Long id, String trackStatType) {
        TrackStat trackStat = new TrackStat();
        trackStat.setTrackId(id);
        trackStat.setStatType(trackStatType);
        trackStat.setStatNum(new Random().nextInt(1000));
        this.trackStatMapper.insert(trackStat);
    }

    /**
     * 删除声音
     *
     * @param id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeTrackInfo(Long id) {
        //根据id获取声音的信息
        TrackInfo trackInfo = trackInfoMapper.selectById(id);
        //逻辑删除声音信息表
        trackInfoMapper.deleteById(id);
        //注意：删除声音还需要更新声音列表的order_num
        trackInfoMapper.updateOrderNum(trackInfo.getAlbumId(), trackInfo.getOrderNum());
        //删除声音统计表
        LambdaQueryWrapper<TrackStat> trackStatLambdaQueryWrapper = new LambdaQueryWrapper<>();
        trackStatLambdaQueryWrapper.eq(TrackStat::getTrackId, id);
        trackStatMapper.delete(trackStatLambdaQueryWrapper);

        //修改专辑信息表中的包含声音总数字段
        Long albumId = trackInfo.getAlbumId();
        AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
        albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount() - 1);
        albumInfoMapper.updateById(albumInfo);

        //删除云点播中的数据
        vodService.removeTrack(trackInfo.getMediaFileId());

    }

    /**
     * 修改声音信息
     *
     * @param id
     * @param trackInfoVo
     */
    @Override
    public void updateTrackInfo(Long id, TrackInfoVo trackInfoVo) {
        TrackInfo trackInfo = this.getById(id);
        //获取原来声音的 mediaFileId
        String oldMediaFileId = trackInfo.getMediaFileId();
        //属性拷贝
        BeanUtils.copyProperties(trackInfoVo, trackInfo);
        if (!oldMediaFileId.equals(trackInfoVo.getMediaFileId())) {
            //说明当前音频文件被修改了，大小，类型、url，时长被修改
            TrackMediaInfoVo trackMediaInfo = vodService.getTrackMediaInfo(trackInfoVo.getMediaFileId());
            //	判断对象不为空.
            if (null == trackMediaInfo) {
                //	抛出异常
                throw new GuiguException(ResultCodeEnum.VOD_FILE_ID_ERROR);
            }
            trackInfo.setMediaDuration(trackMediaInfo.getDuration());
            trackInfo.setMediaUrl(trackMediaInfo.getMediaUrl());
            trackInfo.setMediaSize(trackMediaInfo.getSize());
            trackInfo.setMediaType(trackMediaInfo.getType());
            vodService.removeTrack(oldMediaFileId);
        }
        this.updateById(trackInfo);
    }

    /**
     * 获取专辑声音列表
     *
     * @param trackListVoPage
     * @param albumId
     * @param userId
     */
    @Override
    public void getAlbumTrackPage(Page<AlbumTrackListVo> trackListVoPage, Long albumId, Long userId) {

        Page<AlbumTrackListVo> albumTrackListVoPage = trackInfoMapper.getAlbumTrackPage(trackListVoPage, albumId);
        // 获取当前页数据
        List<AlbumTrackListVo> albumTrackListVoList = albumTrackListVoPage.getRecords();
        //  主要设置是否需要付费字段 isShowPaidMark;
        AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
        //  判断当前用户是否登录
        if (null == userId) {
            //  说明未登录！需要设置当前试听的声音免费 isShowPaidMark = false，其他声音收费 isShowPaidMark = true;
            //  先找到免费试听的集数; 先找到专辑对象;
            //  判断专辑类型不是免费的
            if (!albumInfo.getPayType().equals(SystemConstant.ALBUM_PAY_TYPE_FREE)) {
                Integer tracksForFree = albumInfo.getTracksForFree();
                //  select * from track_info where order_num > 5 and album_id = 1429;
                albumTrackListVoList.stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > tracksForFree)
                        .forEach(albumTrackListVo -> albumTrackListVo.setIsShowPaidMark(true));
            }
            //  返回数据
        } else {
            //  获取到当前用户对象
            Result<UserInfoVo> userInfoVoResult = this.userInfoFeignClient.getUserInfoVo(userId);
            //  获取数据
            UserInfoVo userInfoVo = userInfoVoResult.getData();
            //  声明一个字段;
            boolean isNeedPaidMark = false;
            //  说明用户登录; 判断当前专辑的类型;
            if (SystemConstant.ALBUM_PAY_TYPE_VIPFREE.equals(albumInfo.getPayType())) {
                //  判断当前专辑是vip免费; 判断当前用户是否是vip; is_vip字段;
                if ((1 == userInfoVo.getIsVip() && userInfoVo.getVipExpireTime().before(new Date())) || userInfoVo.getIsVip() == 0) {
                    isNeedPaidMark = true;
                }
            } else if (SystemConstant.ALBUM_PAY_TYPE_REQUIRE.equals(albumInfo.getPayType())) {
                //  当前专辑是付费类型
                isNeedPaidMark = true;
            }
            //  统一处理付费情况：
            if (isNeedPaidMark) {
                //  除去用户购买的专辑或购买的声音之外{user_paid_album，user_paid_track}，要付费！
                //  获取需要付费的声音Id 列表;
                List<AlbumTrackListVo> trackListVoList = albumTrackListVoList.stream().
                        filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > albumInfo.getTracksForFree()).collect(Collectors.toList());
                List<Long> trackIdNeedPaidList = trackListVoList.stream().map(AlbumTrackListVo::getTrackId).collect(Collectors.toList());
                //  远程调用
                Result<Map<Long, Integer>> mapResult = userInfoFeignClient.userIsPaidTrack(albumId, trackIdNeedPaidList);
                //  获取数据
                Assert.notNull(mapResult, "付费声音结果集为空");
                //  map.put(trackId,1): 当前声音已购买，map.put(trackId,0): 当前声音未购买
                Map<Long, Integer> map = mapResult.getData();
                //  循环遍历
                for (AlbumTrackListVo albumTrackListVo : trackListVoList) {
                    //  设置当前声音是否需要付费;
                    //                    if (map.get(albumTrackListVo.getTrackId()) == 1) {
                    //                        albumTrackListVo.setIsShowPaidMark(false);
                    //                    } else {
                    //                        albumTrackListVo.setIsShowPaidMark(true);
                    //                    }
                    //  代码优化：
                    albumTrackListVo.setIsShowPaidMark(map.get(albumTrackListVo.getTrackId()) == 1 ? false : true);
                }
            }
        }
    }

    /**
     * 更新 声音播放量 专辑播放量
     *
     * @param trackStatMqVo
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateTrackStat(TrackStatMqVo trackStatMqVo) {
        //  更新声音播放量
        trackInfoMapper.updateTrackStat(trackStatMqVo.getTrackId(), trackStatMqVo.getStatType(), trackStatMqVo.getCount());

        if (SystemConstant.TRACK_STAT_PLAY.equals(trackStatMqVo.getStatType())) {
            //  更新专辑播放量
            albumInfoMapper.updateAlbumStat(trackStatMqVo.getAlbumId(), SystemConstant.ALBUM_STAT_PLAY, trackStatMqVo.getCount());
        }
    }

    /**
     * 构建用户声音分级购买列表
     *
     * @param trackId
     * @return
     */
    @Override
    public List<Map<String, Object>> findUserTrackPaidList(Long trackId) {
        //  获取声音对象
        TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
        LambdaQueryWrapper<TrackInfo> trackInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //  获取到当前专辑下当前点击声音后的所有声音列表
        trackInfoLambdaQueryWrapper.eq(TrackInfo::getAlbumId, trackInfo.getAlbumId())
                .gt(TrackInfo::getOrderNum, trackInfo.getOrderNum());
        List<TrackInfo> trackInfoList = trackInfoMapper.selectList(trackInfoLambdaQueryWrapper);
        //  获取声音Id列表
        List<Long> trackIdList = trackInfoList.stream().map(TrackInfo::getId).collect(Collectors.toList());
        //  远程调用
        //  远程获取用户已经购买的声音列表
        Result<List<Long>> userPaidTrackIdListResult = userInfoFeignClient.findUserPaidTrackList(trackInfo.getAlbumId());
        Assert.notNull(userPaidTrackIdListResult, "用户购买的声音列表结果为空");
        List<Long> userPaidTrackIdList = userPaidTrackIdListResult.getData();
        //  过滤用户购买过的声音
        List<Long> userNoPaidTrackIdList = trackIdList.stream().filter(tId -> !userPaidTrackIdList.contains(tId)).collect(Collectors.toList());
        //  声明集合对象
        List<Map<String, Object>> trackList = new ArrayList<>();
        //  获取专辑对象
        AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
        //  4.  构建map集合返回数据；
        // 循环处理不同的情况
        if (userNoPaidTrackIdList.size() >= 0) {
            //  创建mpa 集合
            Map<String, Object> hashMap = new HashMap<>();
            hashMap.put("name", "本集");
            //  本集的钱=当前专辑的价格;
            hashMap.put("price", albumInfo.getPrice());
            //  用户要购买的集数;
            hashMap.put("trackCount", 0);
            trackList.add(hashMap);
        }
        for (int i = 0; i <= 50; i += 10) {
            if (userNoPaidTrackIdList.size() > i) {
                // 创建map集合
                Map<String, Object> hashMap = new HashMap<>();
                int count = Math.min(userNoPaidTrackIdList.size(), i + 10);
                hashMap.put("name", "后" + count + "集");
                // 本集的钱=当前专辑的价格
                hashMap.put("price", albumInfo.getPrice().multiply(new BigDecimal(String.valueOf(count))));
                // 用户要购买的集数
                hashMap.put("trackCount", count);
                trackList.add(hashMap);
            }
        }
//        //  后10集以内的数据;   8集-本集，后集;   18-本集，后10集, 后18集
//        if (userNoPaidTrackIdList.size() > 0 && userNoPaidTrackIdList.size() <= 10) {
//            //  创建mpa 集合
//            Map<String, Object> hashMap = new HashMap<>();
//            int count = userNoPaidTrackIdList.size();
//            hashMap.put("name", "后" + count + "集");
//            //  本集的钱=当前专辑的价格;
//            hashMap.put("price", albumInfo.getPrice().multiply(new BigDecimal(String.valueOf(count))));
//            //  用户要购买的集数;
//            hashMap.put("trackCount", count);
//            trackList.add(hashMap);
//        }
//        //  判断
//        if (userNoPaidTrackIdList.size() > 10) {
//            //  创建mpa 集合
//            Map<String, Object> hashMap = new HashMap<>();
//            hashMap.put("name", "后10集");
//            //  本集的钱=当前专辑的价格;
//            hashMap.put("price", albumInfo.getPrice().multiply(new BigDecimal(String.valueOf("10"))));
//            //  用户要购买的集数;
//            hashMap.put("trackCount", 10);
//            trackList.add(hashMap);
//        }
//        //  18
//        if (userNoPaidTrackIdList.size() > 10 && userNoPaidTrackIdList.size() <= 20) {
//            //  创建mpa 集合
//            Map<String, Object> hashMap = new HashMap<>();
//            int count = userNoPaidTrackIdList.size();
//            hashMap.put("name", "后" + count + "集");
//            //  本集的钱=当前专辑的价格;
//            hashMap.put("price", albumInfo.getPrice().multiply(new BigDecimal(String.valueOf(count))));
//            //  用户要购买的集数;
//            hashMap.put("trackCount", count);
//            trackList.add(hashMap);
//        }
//        //  判断
//        if (userNoPaidTrackIdList.size() > 20) {
//            //  创建mpa 集合
//            Map<String, Object> hashMap = new HashMap<>();
//            hashMap.put("name", "后20集");
//            //  本集的钱=当前专辑的价格;
//            hashMap.put("price", albumInfo.getPrice().multiply(new BigDecimal(String.valueOf("20"))));
//            //  用户要购买的集数;
//            hashMap.put("trackCount", 20);
//            trackList.add(hashMap);
//        }
//
//        //  18
//        if (userNoPaidTrackIdList.size() > 20 && userNoPaidTrackIdList.size() <= 30) {
//            //  创建mpa 集合
//            Map<String, Object> hashMap = new HashMap<>();
//            int count = userNoPaidTrackIdList.size();
//            hashMap.put("name", "后" + count + "集");
//            //  本集的钱=当前专辑的价格;
//            hashMap.put("price", albumInfo.getPrice().multiply(new BigDecimal(String.valueOf(count))));
//            //  用户要购买的集数;
//            hashMap.put("trackCount", count);
//            trackList.add(hashMap);
//        }
//        //  判断
//        if (userNoPaidTrackIdList.size() > 30) {
//            //  创建mpa 集合
//            Map<String, Object> hashMap = new HashMap<>();
//            hashMap.put("name", "后30集");
//            //  本集的钱=当前专辑的价格;
//            hashMap.put("price", albumInfo.getPrice().multiply(new BigDecimal(String.valueOf("30"))));
//            //  用户要购买的集数;
//            hashMap.put("trackCount", 30);
//            trackList.add(hashMap);
//        }
        return trackList;
    }

    @Override
    public List<TrackInfo> findPaidTrackInfoList(Long trackId, Integer trackCount) {
        //  创建声音集合列表：
        List<TrackInfo> paidTrackInfoList = new ArrayList<>();
        //  1. 先获取到声音对象; select * from track_info where id = 48241;
        TrackInfo trackInfo = this.getById(trackId);
        //  2.  判断用户购买的集数;
        if (trackCount > 0) {
            //  3.  找到用户已购买的集合列表：
            Result<List<Long>> trackIdListResult = userInfoFeignClient.findUserPaidTrackList(trackInfo.getAlbumId());
            Assert.notNull(trackIdListResult, "用户购买声音Id列表为空");
            List<Long> paidTrackIdList = trackIdListResult.getData();
            //  4.  查询数据; select * from track_info where album_id = 1429 and order_num > 6 and id not in (48244,48245,,48246) limit 10;
            //  构建查询条件
            LambdaQueryWrapper<TrackInfo> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(TrackInfo::getAlbumId, trackInfo.getAlbumId()).gt(TrackInfo::getOrderNum, trackInfo.getOrderNum());
            if (paidTrackIdList.size() > 0) {
                wrapper.notIn(TrackInfo::getId, paidTrackIdList);
            }
            //  限制查询数量：
            wrapper.last(" limit " + trackCount);
            //  接收数据
            paidTrackInfoList = trackInfoMapper.selectList(wrapper);
        } else {
            paidTrackInfoList.add(trackInfo);
        }
        //  返回集合列表
        return paidTrackInfoList;
    }
}
